home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 4
/
The 640 Meg Shareware Studio CD-ROM Volume IV (Data Express)(1994).ISO
/
clang
/
cujaug93.zip
/
WEBER.ZIP
/
MENU.C
< prev
next >
Wrap
Text File
|
1993-03-13
|
32KB
|
879 lines
/***************************************************************
* file: MENU.C
* purpose:
* menubar functions for simple gui
* contains:
* menu_open(MENU_ITEM menubar[],short number_of_items); draws a menubar
* menu_message_handler(MESSAGE *message,MENU_ITEM *menu); handles menu messages
* menu_close(MENU_ITEM menubar[]); erases a menubar
* menu_modify(MENU_ITEM menubar[],short menu_id,unsigned short status); modifies the status of a menu item, ACTIVE, GRAY or HIDDEN
* menu_clear(MENU_ITEM menubar[]); clear any open popups
* popup_open(POPUP_ITEM popup[],short number_of_items); draws a popup
* popup_message_handler(MESSAGE *message,POPUP_ITEM *popup); handles popup messages
* popup_close(POPUP_ITEM popup[]); erases a popup
* popup_modify(POPUP_ITEM popup[],short popup_id,unsigned short status); modifies the status of a popup item, ACTIVE, GRAY or HIDDEN
* system: Written for the flash graphics library in Zortech 3.0
* copyright: 1991 by David Weber. All rights reserved.
* This software can be used for any purpose as object, library or executable.
* It cannot be sold for profit as source code.
* history:
* 12-22-91 - initial code
* 01-31-93 - this code is now obsolete, see the CPP gui package
**************************************************************/
#include <stdio.h>
#include <string.h>
#include "gui.h"
/* local data */
static MENU_ITEM *menu_item_is_selected = NULL;
static MENU_ITEM *menu_last_seen = NULL;
/* local prototypes */
static void selection_focus(short x1,short y1,short x2,short y2);
static void selection_unfocus(short x1,short y1,short x2,short y2);
static short menu_draw_text(short x,short y,char *str,unsigned short status);
static short menu_clear_any_items(MENU_ITEM *menu);
static void menu_select_item(MENU_ITEM *menu);
static void menu_clear_item(MENU_ITEM *menu);
static void menu_select_previous_item(MENU_ITEM *first,MENU_ITEM *current);
static void menu_select_next_item(MENU_ITEM *first,MENU_ITEM *current);
static void menu_default_message_handler(MESSAGE *message);
static MENU_ITEM *menu_current(MENU_ITEM *first);
static void menu_modify_draw(MENU_ITEM *menu);
static short popup_from_menu(MENU_ITEM *first,MENU_ITEM *active);
static void popup_clear_any_item(POPUP_ITEM *popup);
static void popup_select_item(POPUP_ITEM *popup);
static void popup_clear_item(POPUP_ITEM *popup);
static void popup_select_previous_item(POPUP_ITEM *first,POPUP_ITEM *current);
static void popup_select_next_item(POPUP_ITEM *first,POPUP_ITEM *current);
static POPUP_ITEM *popup_current(POPUP_ITEM *first);
static void popup_modify_draw(POPUP_ITEM *popup);
/************************************************
* function: short menu_open(MENU_ITEM menubar[],short number_of_items)
* register a menubar, initialize the hotspots and draw it
* parameters: array of menu items in menu and number of items to expect
* returns: 1 opened or 0 if failed cuz of lack of resources or bad data
************************************************/
short menu_open(MENU_ITEM menubar[],short number_of_items)
{
fg_box_t menu_area;
short i,j,text_x,text_y,cell_height;
MENU_ITEM *m,*m2;
POPUP_ITEM *p;
MESSAGE error;
i = 0; /* verify parameters */
if (number_of_items < 0 || number_of_items > MENU_MAX_ITEMS)
i = 1;
else
for (j = 0 ; j < number_of_items ; j++)
{
m = &menubar[j];
if (m->name == NULL || (m->status & ~MENU_BITS) ||
m->accelerator < KEY_MIN || m->accelerator > KEY_MAX ||
m->number_of_popup_items < 0 || m->number_of_popup_items > POPUP_MAX_ITEMS)
i = 1;
}
if (i)
{
error.id = gui_errno = M_INVALID_PARMS;
error.data.ptr_data = menu_open;
message_send(&error);
return 0;
}
fg_msm_hidecursor();
cell_height = gui_char_height + 6;
text_y = 3;
if (gui_char_height + gui_char_height/2 > cell_height)
{
cell_height = gui_char_height + gui_char_height/2;
text_y = gui_char_height/4;
}
menu_area[FG_X1] = fg.displaybox[FG_X1]; /* coordinates of menubar */
menu_area[FG_X2] = fg.displaybox[FG_X2];
menu_area[FG_Y1] = fg.displaybox[FG_Y2] - cell_height;
menu_area[FG_Y2] = fg.displaybox[FG_Y2];
fg_boxclip(fg.displaybox,menu_area,menu_area);
if (!object_add(OBJECT_MENU,(GENERIC_MESSAGE_HANDLER)menu_message_handler,menubar,menu_area))
{ /* add object to active list */
fg_msm_showcursor();
fg_flush();
return 0;
}
fg_fillbox(COLOR_MENU_BACKGROUND,FG_MODE_SET,~0,menu_area); /* draw bar */
fg_drawbox(COLOR_MENU_FOREGROUND,FG_MODE_SET,~0,FG_LINE_SOLID,menu_area,fg.displaybox);
text_x = fg.displaybox[FG_X1] + 2 * gui_char_width;
text_y += menu_area[FG_Y1];
for (i = 0, m2 = NULL ; i < number_of_items ; i++)
{
m = &menubar[i];
m->screen[FG_X1] = text_x-2*gui_char_width; /* locate hotspots */
m->screen[FG_Y1] = menu_area[FG_Y1];
m->screen[FG_Y2] = menu_area[FG_Y2];
text_x = menu_draw_text(text_x,text_y,m->name,m->status); /* draw text */
m->screen[FG_X2] = text_x + 2 * gui_char_width;
text_x += 4 * gui_char_width;
if (m->popup != NULL)
{ /* link popup items */
for (j = 0, p = m->popup ; j < m->number_of_popup_items-1 ; j++, p++)
p->next = p + 1;
p->next = NULL;
}
m->next = NULL; /* link menu items */
if (m2 != NULL)
m2->next = m;
m2 = m;
}
fg_msm_showcursor();
fg_flush();
return 1;
}
/************************************************
* function: void menu_message_handler(MESSAGE *message,MENU_ITEM *menu)
* handles messages for menu objects
* parameters: pointer to message, pointer to object data
* returns: nothing
************************************************/
void menu_message_handler(MESSAGE *message,MENU_ITEM *menu)
{
MENU_ITEM *m;
POPUP_ITEM *p;
short key,x,y;
menu_item_is_selected = NULL;
switch (message->id)
{
case M_KEY:
key = message->data.short_data.x;
input_handler_set_default(menu_default_message_handler);
menu_last_seen = menu;
for (m = menu ; m != NULL ; m = m->next)
{
if (m->status & MENU_SELECTED)
{ /* if menu item selected */
menu_item_is_selected = m; /* found a selected item */
if (key == RETURN && m->popup == NULL)
{ /* select current item */
message->id = m->id;
return;
}
if (key == LEFTARROW)
{ /* select previous item */
menu_select_previous_item(menu,m);
message->id = M_NONE;
return;
}
if (key == RIGHTARROW)
{ /* select next menu item */
menu_select_next_item(menu,m);
message->id = M_NONE;
return;
}
if (key == SHIFTTAB)
{ /* select previous popup or menu */
if (m->popup == NULL || popup_current(m->popup) == m->popup)
{
menu_select_previous_item(menu,m);
m = menu_current(menu);
}
message->data.short_data.x = UPARROW;
message_send_object(message,(void *) m->popup);
message->id = M_NONE;
return;
}
if (key == TAB)
{ /* select next popup or menu item */
if (m->popup == NULL || popup_current(m->popup)->next == NULL)
menu_select_next_item(menu,m);
else
{
message->data.short_data.x = DOWNARROW;
message_send_object(message,(void *) m->popup);
}
message->id = M_NONE;
return;
}
}
if (m->status & MENU_ACTIVE && m->accelerator == key)
{ /* found an accelerator key */
if (m->popup != NULL)
popup_from_menu(menu,m);
else
{
menu_clear_any_items(menu);
menu_select_item(m);
}
message->id = m->id;
return;
}
if (m->popup != NULL)
{ /* check accelerators on popup attached to menubar item */
for (p = m->popup ; p != NULL ; p = p->next)
if (p->status & MENU_ACTIVE && p->accelerator == key)
{
if ((m->status & MENU_SELECTED) == 0)
popup_from_menu(menu,m);
if ((p->status & MENU_SELECTED) == 0)
{
popup_clear_any_item(m->popup);
popup_select_item(p);
}
message->id = p->id;
return;
}
}
}
break;
case M_MOUSE_LEFT:
case M_MOUSE_CENTER:
case M_MOUSE_RIGHT:
x = message->data.short_data.x;
y = message->data.short_data.y;
for (m = menu ; m != NULL ; m = m->next)
{
if (m->status & MENU_SELECTED)
{
input_handler_set_default(menu_default_message_handler);
menu_item_is_selected = m; /* found a selected item */
}
if (fg_pt_inbox(m->screen,x,y))
{ /* menu item selected */
if (m->status & MENU_ACTIVE)
{
if (m->popup != NULL)
popup_from_menu(menu,m);
else
{
menu_clear_any_items(menu);
menu_select_item(m);
}
message->id = m->id;
return;
}
message->id = M_NONE;
return;
}
}
break;
default:
return;
}
}
/************************************************
* function: short menu_close(MENU_ITEM menubar[])
* parameters: pointer to previously opened menubar
* returns: 1 if closed or 0 if failed
************************************************/
short menu_close(MENU_ITEM menubar[])
{
short ret;
MENU_ITEM *m;
fg_msm_hidecursor();
if ((ret = object_remove(menubar)) != 0)
for (m = menubar ; m != NULL ; m = m->next)
m->status &= ~MENU_SELECTED;
fg_msm_showcursor();
fg_flush();
return ret;
}
/************************************************
* function: short menu_modify(MENU_ITEM menubar[],short menu_id,unsigned short status)
* set the status of an element in a previously opened menubar or associated
* popup and redraw it
* This will set only MENU_ACTIVE, MENU_GRAY or MENU_HIDDEN
* parameters: menu array, id of menu or popup element to set, new status value
* returns: 1 if set or 0 if not opened or improper id
************************************************/
short menu_modify(MENU_ITEM menubar[],short menu_id,unsigned short status)
{
MENU_ITEM *m;
POPUP_ITEM *p;
if (object_exists(menubar) == NULL)
return 0;
for (m = menubar ; m != NULL ; m = m->next)
{
if (m->id == menu_id) /* check menu */
{
m->status = (m->status & ~MENU_STATUS_MASK) | (status & MENU_STATUS_MASK);
menu_modify_draw(m);
if (m->status & MENU_SELECTED)
if ((m->status & MENU_ACTIVE) == 0)
menu_select_next_item(menubar,m);
return 1;
}
for (p = m->popup ; p != NULL ; p = p->next) /* check attached popups */
if (p->id == menu_id)
{
p->status = (p->status & ~MENU_STATUS_MASK) | (status & MENU_STATUS_MASK);
popup_modify_draw(p);
if (p->status & MENU_SELECTED)
if ((p->status & MENU_ACTIVE) == 0)
popup_select_next_item(m->popup,p);
return 1;
}
}
return 0;
}
/************************************************
* function: short menu_clear(MENU_ITEM menubar[])
* parameters: pointer to previously opened menubar
* returns: 1 if cleared or 0 if failed
************************************************/
short menu_clear(MENU_ITEM menubar[])
{
if (object_exists(menubar) == NULL)
return 0;
menu_clear_any_items(menubar);
return 1;
}
/************************************************
* function: short popup_open(POPUP_ITEM popup[],short number_of_items,short x,short y)
* register a popup, initialize the hotspots and draw it
* parameters: array of popup items in popup, number of items to expect and screen location
* returns: 1 opened or 0 if failed cuz of lack of resources
************************************************/
short popup_open(POPUP_ITEM popup[],short number_of_items,short x,short y)
{
fg_box_t popup_area;
short i,j,text_y,right_x,cell_height;
POPUP_ITEM *p,*p2;
MESSAGE error;
i = 0; /* verify parameters */
if (number_of_items < 0 || number_of_items > POPUP_MAX_ITEMS)
i = 1;
else
for (j = 0 ; j < number_of_items ; j++)
{
p = &popup[j];
if (p->name == NULL || (p->status & ~MENU_BITS) ||
p->accelerator < KEY_MIN || p->accelerator > KEY_MAX)
i = 1;
}
if (i)
{
error.id = gui_errno = M_INVALID_PARMS;
error.data.ptr_data = menu_open;
message_send(&error);
return 0;
}
fg_msm_hidecursor();
cell_height = gui_char_height + 6;
popup_area[FG_X1] = x; /* coordinates of popup */
popup_area[FG_Y1] = y - number_of_items * cell_height;
popup_area[FG_X2] = x;
popup_area[FG_Y2] = y;
for (i = 0 ; i < number_of_items ; i++)
{ /* maximum string width */
right_x = x + (strlen(popup[i].name)+2) * gui_char_width;
if (right_x > popup_area[FG_X2])
popup_area[FG_X2] = right_x;
}
fg_boxclip(fg.displaybox,popup_area,popup_area);
if (!object_add(OBJECT_POPUP,(GENERIC_MESSAGE_HANDLER)popup_message_handler,popup,popup_area))
{ /* add to active object list */
fg_msm_showcursor();
fg_flush();
return 0;
}
fg_fillbox(COLOR_MENU_BACKGROUND,FG_MODE_SET,~0,popup_area); /* draw popup */
fg_drawbox(COLOR_MENU_FOREGROUND,FG_MODE_SET,~0,FG_LINE_SOLID,popup_area,fg.displaybox);
text_y = y + (cell_height-gui_char_height)/2;
for (i = 0, p2 = NULL ; i < number_of_items ; i++)
{
p = &popup[i];
p->screen[FG_X1] = x; /* locate hotspots */
p->screen[FG_X2] = right_x;
p->screen[FG_Y2] = y;
text_y -= cell_height;
y -= cell_height;
p->screen[FG_Y1] = y;
(void) menu_draw_text(x+gui_char_width,text_y,p->name,p->status); /* draw text */
p->next = NULL; /* link popups */
if (p2 != NULL)
p2->next = p;
p2 = p;
}
fg_msm_showcursor();
fg_flush();
return 1;
}
/************************************************
* function: void popup_message_handler(MESSAGE *message,POPUP_ITEM *popup)
* handles messages for popup objects
* parameters: pointer to message, pointer to object data
* returns: nothing
************************************************/
void popup_message_handler(MESSAGE *message,POPUP_ITEM *popup)
{
POPUP_ITEM *p;
short key,x,y;
switch (message->id)
{
case M_KEY:
key = message->data.short_data.x;
for (p = popup ; p != NULL ; p = p->next)
{
if (p->status & MENU_SELECTED) /* if popup is open and selected */
{
if (key == DOWNARROW) /* move to next item */
{
popup_select_next_item(popup,p);
message->id = M_NONE;
return;
}
if (key == UPARROW) /* move to previous item */
{
popup_select_previous_item(popup,p);
message->id = M_NONE;
return;
}
if (key == RETURN) /* current item selected */
{
message->id = p->id;
return;
}
}
if (p->status & MENU_ACTIVE && p->accelerator == key)
{
popup_clear_any_item(popup);
popup_select_item(p);
message->id = p->id; /* accelerator key selected */
return;
}
}
break;
case M_MOUSE_LEFT:
case M_MOUSE_CENTER:
case M_MOUSE_RIGHT:
x = message->data.short_data.x;
y = message->data.short_data.y;
for (p = popup ; p != NULL ; p = p->next)
if (fg_pt_inbox(p->screen,x,y))
{ /* mouse clicked on item in an open popup */
if (p->status & MENU_ACTIVE)
{
popup_clear_any_item(popup);
popup_select_item(p);
message->id = p->id;
return;
}
message->id = M_NONE;
return;
}
break;
default:
return;
}
}
/************************************************
* function: short popup_close(POPUP_ITEM popup[])
* parameters: pointer to previously opened popup
* returns: 1 if closed or 0 if failed
************************************************/
short popup_close(POPUP_ITEM popup[])
{
short ret;
POPUP_ITEM *p;
fg_msm_hidecursor();
if ((ret = object_remove(popup)) != 0)
for (p = popup ; p != NULL ; p = p->next)
p->status &= ~MENU_SELECTED;
fg_msm_showcursor();
fg_flush();
return ret;
}
/************************************************
* function: short popup_modify(POPUP_ITEM popup[],short popup_id,unsigned short status)
* set the status of an element in a previously opened popup and redraw it
* This will set only MENU_ACTIVE, MENU_GRAY or MENU_HIDDEN
* parameters: popup array, id of element to set, new status value
* returns: 1 if set or 0 if not opened or improper id
************************************************/
short popup_modify(POPUP_ITEM popup[],short popup_id,unsigned short status)
{
POPUP_ITEM *p;
if (object_exists(popup) == NULL)
return 0;
for (p = popup ; p != NULL ; p = p->next)
if (p->id == popup_id)
{
p->status = (p->status & ~MENU_STATUS_MASK) | (status & MENU_STATUS_MASK);
popup_modify_draw(p);
if (p->status & MENU_SELECTED)
if ((p->status & MENU_ACTIVE) == 0)
popup_select_next_item(popup,p);
return 1;
}
return 0;
}
/* ---------------- LOCAL FUNCTIONS ---------------- */
/* highlight a menu/popup selection */
static void selection_focus(short x1,short y1,short x2,short y2)
{
fg_box_t selection;
fg_msm_hidecursor();
fg_make_box(selection,x1,y1,x2,y2);
fg_drawbox(COLOR_MENU_FOCUS,FG_MODE_SET,~0,FG_LINE_SOLID,selection,fg.displaybox);
selection[FG_X1]++;
selection[FG_Y1]++;
selection[FG_X2]--;
selection[FG_Y2]--;
fg_drawbox(COLOR_MENU_FOCUS,FG_MODE_SET,~0,FG_LINE_SOLID,selection,fg.displaybox);
fg_msm_showcursor();
fg_flush();
}
/* clear a menu/popup selection */
static void selection_unfocus(short x1,short y1,short x2,short y2)
{
fg_box_t selection;
fg_msm_hidecursor();
fg_make_box(selection,x1,y1,x2,y2);
fg_drawbox(COLOR_MENU_BACKGROUND,FG_MODE_SET,~0,FG_LINE_SOLID,selection,fg.displaybox);
selection[FG_X1]++;
selection[FG_Y1]++;
selection[FG_X2]--;
selection[FG_Y2]--;
fg_drawbox(COLOR_MENU_BACKGROUND,FG_MODE_SET,~0,FG_LINE_SOLID,selection,fg.displaybox);
fg_msm_showcursor();
fg_flush();
}
/* ---------------- MENUS ---------------- */
/* close any open popups in menu and clear selected items, return 1 if OK or 0 if fail */
static short menu_clear_any_items(MENU_ITEM *menu)
{
MENU_ITEM *m;
for (m = menu ; m != NULL ; m = m->next)
if (m->status & MENU_SELECTED)
{
menu_clear_item(m);
if(m->popup != NULL)
{
if (!popup_close(m->popup))
return 0;
}
}
return 1;
}
/* highlight a menu item and mark status as selected */
static void menu_select_item(MENU_ITEM *menu)
{
selection_focus(menu->screen[FG_X1]+gui_char_width,menu->screen[FG_Y1]+1,menu->screen[FG_X2]-gui_char_width,menu->screen[FG_Y2]-1);
menu->status |= MENU_SELECTED;
}
/* clear a menu item's highlights and status flag */
static void menu_clear_item(MENU_ITEM *menu)
{
selection_unfocus(menu->screen[FG_X1]+gui_char_width,menu->screen[FG_Y1]+1,menu->screen[FG_X2]-gui_char_width,menu->screen[FG_Y2]-1);
menu->status &= ~MENU_SELECTED;
}
/* move to previous menu item */
static void menu_select_previous_item(MENU_ITEM *first,MENU_ITEM *current)
{
MENU_ITEM *m,*mark;
mark = current;
do
{
for (m = first ; m->next != current && m->next != NULL ; m = m->next)
;
current = m;
if (current == mark)
break;
} while ((current->status & MENU_ACTIVE) == 0);
if (current->popup != NULL)
popup_from_menu(first,current);
else
{
menu_clear_any_items(first);
menu_select_item(current);
}
}
/* move to next menu item */
static void menu_select_next_item(MENU_ITEM *first,MENU_ITEM *current)
{
MENU_ITEM *mark;
mark = current;
do
{
if (current->next == NULL)
current = first;
else
current = current->next;
if (current == mark)
break;
} while ((current->status & MENU_ACTIVE) == 0);
if (current->popup != NULL)
popup_from_menu(first,current);
else
{
menu_clear_any_items(first);
menu_select_item(current);
}
}
/* draw menu text str at coordinates x,y using ACTIVE,GRAY HIDDEN status, return new x value */
static short menu_draw_text(short x,short y,char *str,unsigned short status)
{
short i,color;
for (i = 0 ; str[i] != 0 ; i++)
{
if (status & MENU_GRAY)
color = COLOR_MENU_GRAY;
else if (status & MENU_HIDDEN)
color = COLOR_MENU_BACKGROUND;
else
color = COLOR_MENU_FOREGROUND;
if (str[i] == '&')
{
i++;
if (str[i] == 0)
i--;
if (str[i] != '&' && color == COLOR_MENU_FOREGROUND)
color = COLOR_MENU_HIGHLIGHT;
}
fg_putc(color,FG_MODE_SET,~0,FG_ROT0,x,y,str[i],fg.displaybox);
x += gui_char_width;
}
return x;
}
/* closes any popups left open when a click occurs somewhere */
static void menu_default_message_handler(MESSAGE *message)
{
short key;
if (menu_item_is_selected != NULL) /* close any open menu items */
{
menu_clear_any_items(menu_item_is_selected);
message->id = M_NONE;
}
else if (message->id == M_KEY)
{
key = message->data.short_data.x;
if (key == TAB || key == SHIFTTAB || key == DOWNARROW || key == UPARROW || key == RIGHTARROW || key == LEFTARROW || key == RETURN)
{ /* nothing open, so open first item */
if (menu_last_seen->popup != NULL)
popup_from_menu(menu_last_seen,menu_last_seen);
else
{
menu_clear_any_items(menu_last_seen);
menu_select_item(menu_last_seen);
}
message->id = M_NONE;
}
}
}
/* return a pointer to the currently selected menu item or NULL if none */
static MENU_ITEM *menu_current(MENU_ITEM *first)
{
MENU_ITEM *m;
for (m = first ; m != NULL ; m = m->next)
if (m->status & MENU_SELECTED)
return m;
return NULL;
}
/* redraw a modified menu item */
static void menu_modify_draw(MENU_ITEM *menu)
{
short text_y;
fg_box_t text_area;
fg_msm_hidecursor();
text_y = 3;
if (gui_char_height + gui_char_height/2 > gui_char_height + 6)
text_y = gui_char_height/4;
fg_box_cpy(text_area,menu->screen);
text_area[FG_X1] += 2*gui_char_width;
text_area[FG_Y1] += text_y;
text_area[FG_X2] -= 2*gui_char_width;
text_area[FG_Y2] = text_area[FG_Y1] + gui_char_height - 1;
fg_fillbox(COLOR_MENU_BACKGROUND,FG_MODE_SET,~0,text_area);
menu_draw_text(text_area[FG_X1],text_area[FG_Y1],menu->name,menu->status);
fg_msm_showcursor();
fg_flush();
}
/* ---------------- POPUPS ---------------- */
/* close any open popups and open this popup */
static short popup_from_menu(MENU_ITEM *first,MENU_ITEM *active)
{
short x,dx;
POPUP_ITEM *p;
if (active->popup == NULL || active->number_of_popup_items <= 0)
return 0;
if (!menu_clear_any_items(first))
return 0;
for (p = active->popup, dx = 0 ; p != NULL ; p = p->next) /* find width of popup */
{
x = (strlen(p->name)+2) * gui_char_width;
if (x > dx)
dx = x;
}
x = active->screen[FG_X1]+gui_char_width;
if (x + dx > fg.displaybox[FG_X2]) /* fit within menubar */
x = fg.displaybox[FG_X2] - dx;
if (x < fg.displaybox[FG_X1])
x = fg.displaybox[FG_X1];
if (!popup_open(active->popup,active->number_of_popup_items,x,active->screen[FG_Y1]))
return 0;
menu_select_item(active);
if (active->popup->status & MENU_ACTIVE)
popup_select_item(active->popup);
else
popup_select_next_item(active->popup,active->popup);
return 1;
}
/* highlight a popup item and mark status as selected */
static void popup_select_item(POPUP_ITEM *popup)
{
selection_focus(popup->screen[FG_X1]+1,popup->screen[FG_Y1]+1,popup->screen[FG_X2]-1,popup->screen[FG_Y2]-1);
popup->status |= MENU_SELECTED;
}
/* clear all selected popup items */
static void popup_clear_any_item(POPUP_ITEM *popup)
{
POPUP_ITEM *p;
for (p = popup ; p != NULL ; p = p->next)
if (p->status & MENU_SELECTED)
popup_clear_item(p);
}
/* clear a popup item's highlights and status flag */
static void popup_clear_item(POPUP_ITEM *popup)
{
selection_unfocus(popup->screen[FG_X1]+1,popup->screen[FG_Y1]+1,popup->screen[FG_X2]-1,popup->screen[FG_Y2]-1);
popup->status &= ~MENU_SELECTED;
}
/* move to previous popup item */
static void popup_select_previous_item(POPUP_ITEM *first,POPUP_ITEM *current)
{
POPUP_ITEM *p,*mark;
mark = current;
do
{
for (p = first ; p->next != current && p->next != NULL ; p = p->next)
;
current = p;
if (current == mark)
break;
} while ((current->status & MENU_ACTIVE) == 0);
popup_clear_item(mark);
popup_select_item(current);
}
/* move to next popup item */
static void popup_select_next_item(POPUP_ITEM *first,POPUP_ITEM *current)
{
POPUP_ITEM *mark;
mark = current;
do
{
if (current->next == NULL)
current = first;
else
current = current->next;
if (current == mark)
break;
} while ((current->status & MENU_ACTIVE) == 0);
popup_clear_item(mark);
popup_select_item(current);
}
/* return a pointer to the currently selected popup item or NULL if none */
static POPUP_ITEM *popup_current(POPUP_ITEM *first)
{
POPUP_ITEM *p;
for (p = first ; p != NULL ; p = p->next)
if (p->status & MENU_SELECTED)
return p;
return NULL;
}
/* redraw a modified popup item */
static void popup_modify_draw(POPUP_ITEM *popup)
{
fg_box_t text_area;
fg_msm_hidecursor();
fg_box_cpy(text_area,popup->screen);
text_area[FG_X1] += gui_char_width;
text_area[FG_Y1] += 3;
text_area[FG_X2] -= gui_char_width;
text_area[FG_Y2] = text_area[FG_Y1] + gui_char_height - 1;
fg_fillbox(COLOR_MENU_BACKGROUND,FG_MODE_SET,~0,text_area);
menu_draw_text(text_area[FG_X1],text_area[FG_Y1],popup->name,popup->status);
fg_msm_showcursor();
fg_flush();
}